#include "TFSimilarBondHandler.h"
#include <bondlib/BondContainer.h>
#include <bondlib/AdditionBondInfo.h>
#include <QJsonArray>
#include <QJsonObject>
#include <uam/ServerTimeMgr.h>

bool TfSimilarBondHandler::processCmd(const QJsonObject& cmdObj, const ReqInfo& reqinfo, bool unReg /*= false*/)
{
	m_BondInfo = std::make_shared<CBondInfo>();
	QJsonObject condObj = cmdObj["cond"].toObject();
	if (!condObj.isEmpty())
	{
		QString key = condObj["combkey"].toString();
		if (!key.isEmpty())
		{
			if (!CBondContainer::instance().GetBondInfoByCombKey(key.toUtf8().data(), m_BondInfo.get()))
				return false;
		}
		else if (!(key = condObj["combcode"].toString()).isEmpty())
		{
			if(!CBondContainer::instance().GetBondInfoByCombCode(key.toUtf8().data(), m_BondInfo.get()))
				return false;
		}

		if (!m_BondInfo->IsValidBond() || strlen(m_BondInfo->GetMaturityTerm()) == 0)
			return false;

		m_MatyrityType = getSourceMaturityType(m_BondInfo.get());
		if (m_MatyrityType == MatyrityType_Non)
			return false;
	}

	//获取相似债券
	std::set<int> simiBond;
	std::map<std::string, int> AdditionList;

	//遍历所有的债券
	CBondContainer& gc = CBondContainer::instance();
	int size = gc.GetSize();
	for (int i = 0; i < size; ++i)
	{
		CBondInfo* pBi = gc.GetBond(i);
		if(!pBi->IsValidBond())
			continue;

		//建立增续发对应表
		const CAdditionBondInfo* pAddition = pBi->GetAdditionInfo();
		if (nullptr != pAddition)
		{
			std::string strFirstKey = pAddition->GetFirstIssueKey();
			AdditionList.insert(std::make_pair(pBi->GetCombBondKey(), gc.GetBondIndex(strFirstKey)));
		}

		//判断债券类型 只取二级市场债券MKT_TYPE=2。
		if (strcmp(pBi->GetMarketType(), "2") != 0)
		{
			continue;
		}
		//匹配
		if ((m_BondInfo->IsBondCountry() && pBi->IsBondCountry()) ||//国债
			(0 == strcmp(m_BondInfo->GetBondSubType(), "PBB") && 0 == strcmp(pBi->GetBondSubType(), "PBB")))
		{
			//判断年限
			if (isSimiBond(pBi))
			{
				simiBond.insert(i);
			}
		}
	}

	//增续发券
	if (m_BondInfo->IsAddIssueBond() && !AdditionList.empty())
	{
		auto findIter = AdditionList.find(m_BondInfo->GetCombBondKey());
		if (AdditionList.end() != findIter)
		{
			const CBondInfo* pBond = gc.GetBond(findIter->second);
			if (nullptr != pBond && strcmp(pBond->GetMarketType(), "2") == 0)
			{
				simiBond.insert(findIter->second);
			}
		}
	}

	int count = 0;
	QJsonObject jsRes;
	QJsonArray jsList;

	for (auto index : simiBond)
	{
		CBondInfo* pBond = gc.GetBond(index);
		if(!pBond)
			continue;
		QJsonObject jsItem;
		jsItem["combkey"] = pBond->GetCombBondKey();
		jsItem["combcode"] = pBond->GetCombBondCode();
		jsItem["shortname"] = QString::fromLocal8Bit(pBond->GetBondShortName());
		jsList.append(jsItem);

		if (++count % 20 == 0)
		{
			jsRes["finish"] = 0;
			jsRes["list"] = jsList;

			QJsonDocument doc(jsRes);
            emit sendDataToWeb(reqinfo.m_frameId, reqinfo.m_sid, doc.toJson(QJsonDocument::Compact), reqinfo.m_jsCb);

			QJsonObject emptyObj;
			QJsonArray emptyArr;
			jsRes.swap(emptyObj);
			jsList.swap(emptyArr);
		}
	}

	jsRes["finish"] = 1;
	jsRes["list"] = jsList;
	QJsonDocument doc(jsRes);
    emit sendDataToWeb(reqinfo.m_frameId, reqinfo.m_sid, doc.toJson(QJsonDocument::Compact), reqinfo.m_jsCb);

	return true;
}

bool TfSimilarBondHandler::isSimiBond(CBondInfo* pBi)
{
	//如果是增续发券则剔除
	if (pBi->IsAddIssueBond())
		return false;

	MatyrityType Target = getSimiMaturityType(pBi);
	if (m_MatyrityType == Target)
		return true;

	return false;
}

TfSimilarBondHandler::MatyrityType TfSimilarBondHandler::getSimiMaturityType(const CBondInfo* pBi)
{
	double fYear = pBi->GetRemainYear(ServerTimeMgr::instance().serverTime());

	MatyrityType Type = MatyrityType_Non;
	if (fYear >= 0.16 && fYear <= 0.25) Type = MatyrityType_3M;
	else if (fYear >= 0.41 && fYear <= 0.5) Type = MatyrityType_6M;
	else if (fYear >= 0.66 && fYear <= 0.75) Type = MatyrityType_9M;
	else if (fYear >= 0.84 && fYear <= 1) Type = MatyrityType_1Y;
	else if (fYear >= 1.5 && fYear <= 2) Type = MatyrityType_2Y;
	else if (fYear >= 2.5 && fYear <= 3) Type = MatyrityType_3Y;
	else if (fYear >= 4.5 && fYear <= 5) Type = MatyrityType_5Y;
	else if (fYear >= 6.5 && fYear <= 7) Type = MatyrityType_7Y;
	else if (fYear >= 9.5 && fYear <= 10) Type = MatyrityType_10Y;
	else if (fYear >= 13 && fYear <= 15) Type = MatyrityType_15Y;
	else if (fYear >= 18 && fYear <= 20) Type = MatyrityType_20Y;
	else if (fYear >= 28 && fYear <= 30) Type = MatyrityType_30Y;
	else if (fYear >= 48 && fYear <= 50) Type = MatyrityType_50Y;

	return Type;
}

TfSimilarBondHandler::MatyrityType TfSimilarBondHandler::getSourceMaturityType(const CBondInfo* pBi)
{
	std::string strMaturity = pBi->GetMaturityTerm();

	int nYFindIndex = strMaturity.find('Y', 0);
	int nMFindIndex = strMaturity.find('M', 0);
	int nDFindIndex = strMaturity.find('D', 0);

	double fYear = 0;
	if (nYFindIndex >= 0)
	{
		strMaturity.erase(nYFindIndex, 1);
		fYear = atof(strMaturity.c_str());
	}
	else if (nMFindIndex >= 0)
	{
		strMaturity.erase(nMFindIndex, 1);
		fYear = atof(strMaturity.c_str()) / 12.0;
	}
	else if (nDFindIndex >= 0)
	{
		strMaturity.erase(nDFindIndex, 1);
		fYear = atof(strMaturity.c_str()) / 365.0;
	}

	const double EPSION = 0.01;
	MatyrityType Type;
	if (fabs(fYear - 0.2486) < EPSION) Type = MatyrityType_3M;
	else if (fabs(fYear - 0.4973) < EPSION) Type = MatyrityType_6M;
	else if (fabs(fYear - 0.7514) < EPSION) Type = MatyrityType_9M;
	else if (fabs(fYear - 1) < EPSION) Type = MatyrityType_1Y;
	else if (fabs(fYear - 2) < EPSION) Type = MatyrityType_2Y;
	else if (fabs(fYear - 3) < EPSION) Type = MatyrityType_3Y;
	else if (fabs(fYear - 5) < EPSION) Type = MatyrityType_5Y;
	else if (fabs(fYear - 7) < EPSION) Type = MatyrityType_7Y;
	else if (fabs(fYear - 10) < EPSION) Type = MatyrityType_10Y;
	else if (fabs(fYear - 15) < EPSION) Type = MatyrityType_15Y;
	else if (fabs(fYear - 20) < EPSION) Type = MatyrityType_20Y;
	else if (fabs(fYear - 30) < EPSION) Type = MatyrityType_30Y;
	else if (fabs(fYear - 50) < EPSION) Type = MatyrityType_50Y;
	else Type = MatyrityType_Non;

	return Type;
}
